cmake_minimum_required(VERSION 3.6)

set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "build type")

project(srpc_tutorial
		LANGUAGES C CXX
)

if (WIN32)
	option(SRPC_TUTORIAL_BUILD_STATIC_RUNTIME "Use static runtime" ON)
endif ()

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR})

if (NOT "$ENV{LIBRARY_PATH}" STREQUAL "")
	string(REPLACE ":" ";" LIBRARY_PATH $ENV{LIBRARY_PATH})
	set(CMAKE_SYSTEM_LIBRARY_PATH ${LIBRARY_PATH};${CMAKE_SYSTEM_LIBRARY_PATH})
endif ()

if (NOT "$ENV{CPLUS_INCLUDE_PATH}" STREQUAL "")
	string(REPLACE ":" ";" INCLUDE_PATH $ENV{CPLUS_INCLUDE_PATH})
	set(CMAKE_SYSTEM_INCLUDE_PATH ${INCLUDE_PATH};${CMAKE_SYSTEM_INCLUDE_PATH})
endif ()

find_package(OpenSSL REQUIRED)
find_package(srpc REQUIRED CONFIG HINTS ..)

set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")
if (WIN32)
	find_package(Protobuf CONFIG REQUIRED)
	find_library(LZ4_LIBRARY NAMES lz4)
	if(LZ4_LIBRARY STREQUAL "LZ4_LIBRARY-NOTFOUND")
		find_package(lz4)
		if(lz4_FOUND)
			set(LZ4_LIBRARY ${lz4_LIBRARIES})
		endif()
	endif()
	find_package(Snappy CONFIG REQUIRED)
else ()
	find_package(Protobuf REQUIRED)
endif ()

if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/lz4/lib/lz4.h")
	set(LZ4_LIB lz4)
endif ()

if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/snappy/cmake")
	set(SNAPPY_LIB snappy)
endif ()

if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/workflow/workflow-config.cmake.in")
	find_package(Workflow REQUIRED CONFIG HINTS ../workflow)
endif ()

find_package(ZLIB REQUIRED)

include_directories(
	${OPENSSL_INCLUDE_DIR}
	${CMAKE_CURRENT_BINARY_DIR}
	${Protobuf_INCLUDE_DIR}
	${WORKFLOW_INCLUDE_DIR}
	${SRPC_INCLUDE_DIR}
)

if (WIN32)
	link_directories(${SRPC_LIB_DIR} ${WORKFLOW_LIB_DIR} ${Protobuf_LIB_DIR})
	set(SRPC_GEN_PROGRAM ${SRPC_BIN_DIR}/Debug/srpc_generator.exe)
else ()
	get_filename_component(Protobuf_LIB_DIR ${Protobuf_LIBRARY} DIRECTORY)
	link_directories(${SRPC_LIB_DIR} ${WORKFLOW_LIB_DIR} ${Protobuf_LIB_DIR})
	set(SRPC_GEN_PROGRAM ${SRPC_BIN_DIR}/srpc_generator)
endif ()

### generating codes for echo_pb.proto

set(PROTO_FILE "echo_pb.proto")
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${PROTO_FILE})
add_custom_target(ECHO_PB_CHANGED DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
add_custom_command(
	OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak
	COMMAND ${SRPC_GEN_PROGRAM} ${PROJECT_SOURCE_DIR}/${PROTO_FILE} ${PROJECT_SOURCE_DIR}
	COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak
	DEPENDS ${PROJECT_SOURCE_DIR}/${PROTO_FILE}
	COMMENT "srpc generator for ${PROTO_FILE}"
)
add_custom_target(ECHO_PB_GENERATED DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak)
add_dependencies(ECHO_PB_GENERATED ECHO_PB_CHANGED)

### generating codes for echo_thrift.thrift

set(PROTO_FILE "echo_thrift.thrift")
add_custom_command(
	OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak
	COMMAND ${SRPC_GEN_PROGRAM} ${PROJECT_SOURCE_DIR}/${PROTO_FILE} ${PROJECT_SOURCE_DIR}
	COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak
	DEPENDS ${PROJECT_SOURCE_DIR}/${PROTO_FILE}
	COMMENT "srpc generator for ${PROTO_FILE}"
)
add_custom_target(THRIFT_GENERATED DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak)

### generating codes for helloworld.proto

set(PROTO_FILE "helloworld.proto")
protobuf_generate_cpp(HELLOWORLD_SRCS HELLOWORLD_HDRS ${PROTO_FILE})
add_custom_target(HELLOWORLD_CHANGED DEPENDS ${HELLOWORLD_SRCS} ${HELLOWORLD_HDRS})
add_custom_command(
	OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak
	COMMAND ${SRPC_GEN_PROGRAM} protobuf ${PROJECT_SOURCE_DIR}/${PROTO_FILE} ${PROJECT_SOURCE_DIR}
	COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak
	DEPENDS ${PROJECT_SOURCE_DIR}/${PROTO_FILE}
	COMMENT "srpc generator for ${PROTO_FILE}"
)
add_custom_target(HELLOWORLD_GENERATED DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PROTO_FILE}.bak)
add_dependencies(HELLOWORLD_GENERATED HELLOWORLD_CHANGED)

if (WIN32)
	if (SRPC_TUTORIAL_BUILD_STATIC_RUNTIME)
		set(CompilerFlags
				CMAKE_CXX_FLAGS
				CMAKE_CXX_FLAGS_DEBUG
				CMAKE_CXX_FLAGS_RELEASE
				CMAKE_CXX_FLAGS_MINSIZEREL
				CMAKE_C_FLAGS
				CMAKE_C_FLAGS_DEBUG
				CMAKE_C_FLAGS_RELEASE
				CMAKE_C_FLAGS_MINSIZEREL
				)
		foreach(CompilerFlag ${CompilerFlags})
			string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
		endforeach ()
	endif ()
endif ()

if (WIN32)
	set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   /MP /wd4200")
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /wd4200 /Zc:__cplusplus /std:c++14")
else ()
	set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -Wall -fPIC -pipe -std=gnu90")
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIC -pipe -std=c++14 -fno-exceptions")
endif ()

if (APPLE)
	set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ${CMAKE_FIND_LIBRARY_SUFFIXES})
	find_library(Workflow_LIB workflow HINTS ../workflow/_lib)
	find_library(Srpc_LIB srpc HINTS ../_lib)

	set(SRPC_LIB
		${Srpc_LIB}
		${Workflow_LIB}
		pthread
		OpenSSL::SSL
		OpenSSL::Crypto
		protobuf
		z
		)
elseif (WIN32)
	set(SRPC_LIB
		srpc
		workflow
		ws2_32
		wsock32
		OpenSSL::SSL
		OpenSSL::Crypto
		protobuf::libprotobuf
		ZLIB::ZLIB
		Snappy::snappy
		${LZ4_LIBRARY}
		)
else ()
	set(SRPC_LIB
		srpc
		workflow
		pthread
		OpenSSL::SSL
		OpenSSL::Crypto
		protobuf
		z
		${SNAPPY_LIB}
		${LZ4_LIB}
		)
endif ()

set(TUTORIAL_PB_LIST
	tutorial-01-srpc_pb_server
	tutorial-02-srpc_pb_client
	tutorial-05-brpc_pb_server
	tutorial-06-brpc_pb_client
	tutorial-09-client_task
	tutorial-10-server_async
	tutorial-15-srpc_pb_proxy
	tutorial-16-server_with_metrics
	tutorial-19-custom_filter
)

foreach(src ${TUTORIAL_PB_LIST})
	string(REPLACE "-" ";" arr ${src})
	list(GET arr -1 bin_name)
	add_executable(${bin_name} ${src}.cc ${PROTO_SRCS} ${PROTO_HDRS})
	target_link_libraries(${bin_name} ${SRPC_LIB})
	add_dependencies(${bin_name} ECHO_PB_GENERATED)
endforeach()

set(TUTORIAL_THRIFT_LIST
	tutorial-03-srpc_thrift_server
	tutorial-04-srpc_thrift_client
	tutorial-07-thrift_thrift_server
	tutorial-08-thrift_thrift_client
)

foreach(src ${TUTORIAL_THRIFT_LIST})
	string(REPLACE "-" ";" arr ${src})
	list(GET arr -1 bin_name)
	add_executable(${bin_name} ${src}.cc)
	target_link_libraries(${bin_name} ${SRPC_LIB})
	add_dependencies(${bin_name} THRIFT_GENERATED)
endforeach()

set(TUTORIAL_HELLOWORLD_LIST
	tutorial-11-trpc_pb_server
	tutorial-12-trpc_pb_client
	tutorial-13-trpc_http_server
	tutorial-14-trpc_http_client
)

foreach(src ${TUTORIAL_HELLOWORLD_LIST})
	string(REPLACE "-" ";" arr ${src})
	list(GET arr -1 bin_name)
	add_executable(${bin_name} ${src}.cc ${HELLOWORLD_SRCS} ${HELLOWORLD_HDRS})
	target_link_libraries(${bin_name} ${SRPC_LIB})
	add_dependencies(${bin_name} HELLOWORLD_GENERATED)
endforeach()

if (NOT WIN32)
	set(TUTORIAL_HTTP_LIST
		tutorial-17-http_server
		tutorial-18-http_client
	)

	foreach(src ${TUTORIAL_HTTP_LIST})
		string(REPLACE "-" ";" arr ${src})
		list(GET arr -1 bin_name)
		add_executable(${bin_name} ${src}.cc)
		target_link_libraries(${bin_name} ${SRPC_LIB})
		add_dependencies(${bin_name} ECHO_PB_GENERATED)
	endforeach()
endif ()

set_property(DIRECTORY APPEND PROPERTY
	ADDITIONAL_MAKE_CLEAN_FILES
	${CMAKE_CURRENT_BINARY_DIR}/echo_pb.proto.bak
	${CMAKE_CURRENT_BINARY_DIR}/echo_thrift.proto.bak
	${CMAKE_CURRENT_BINARY_DIR}/helloworld.proto.bak
)

